# coding=utf-8
from phy.uart.ui_uart import *
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
import serial
import serial.tools.list_ports
from tool_base import *
import threading
(UART_ST_NONE, UART_ST_SEND_ERR, UART_ST_NOT_INIT,UART_ST_OPEN_ERR, UART_ST_SAVE_DATA)= range(0,5)
(CMD_REC_DATA,CMD_REC_CLOSE) = range(0, 2)
class uart_cfg_window(QDialog, Ui_uart_cfg_form):
    open_st = False
    cfg = {}
    msg = None
    uart_hd= None
    band_rate_list = [1200,2400,4800,9600,19200,38400,57600,115200]
    data_bits  =[serial.EIGHTBITS]
    sum_list = [serial.PARITY_NONE, serial.PARITY_ODD, serial.PARITY_EVEN]
    stops_list = [serial.STOPBITS_ONE, serial.STOPBITS_TWO, serial.STOPBITS_ONE_POINT_FIVE]
    cmd_lock = threading.Lock()
    repeat_send_mark = False
    repeat_send_data = None
    repeat_send_time = time.time()
    repeat_send_period = 1

    def uart_rec_task(self):
        rec_time = time.time()
        rec_st = 0
        rec_data = bytearray(0)

        while True:
            self.cmd_lock.acquire()
            temp_st = self.open_st
            self.cmd_lock.release()

            self.cmd_lock.acquire()
            repeat_send_mark = self.repeat_send_mark
            self.cmd_lock.release()
            if repeat_send_mark == True:
                if (time.time() - self.repeat_send_time)*1000 > self.repeat_send_period:
                    self.repeat_send_time = time.time()
                    self.uart_hd.write(self.repeat_send_data)
                    self.uart_hd.flush()

            if temp_st == False:
                self.uart_hd.close()
                self.cmd_lock.acquire()
                self.open_st = False
                self.cmd_lock.release()
                self.uart_hd = None
                return
            else:
                if self.uart_hd.in_waiting:
                    rec_st = 1
                    rec_time = time.time() 
                    temp = self.uart_hd.read(1)
                    rec_data.extend(temp)

                if rec_st == 1:
                    if (time.time() - rec_time)*1000 >  self.cfg['rec_timeout']:
                        rec_st = 0
                        if self.msg != None:
                            self.msg.emit({'cmd':CMD_REC_DATA, 'data':rec_data})
                        rec_data = bytearray(0)

    def get_cfg_info(self):
        cfg = {}
        cfg['port'] = self.uart_port_comboBox.currentText()
        cfg['bandrate'] = self.uart_bandrate_comboBox.currentIndex()
        cfg['data_bits'] = self.uart_bitscomboBox.currentIndex()
        cfg['sum'] = self.uart_sum_comboBox.currentIndex()
        cfg['stops'] = self.stop_cnt_comboBox.currentIndex()
        cfg['rec_timeout'] = self.spinBox.value()
        return cfg
    
    def set_cfg(self, cfg:dict):
        try:
            for key, val in cfg.items():
                if 'port' == key:
                    for i in range(0, 512):
                        if val == self.uart_port_comboBox.currentText():
                            self.uart_port_comboBox.setCurrentIndex(i)
                            break
                if 'bandrate' == key:
                    self.uart_bandrate_comboBox.setCurrentIndex(int(val))
                if 'data_bits' == key:
                    self.uart_bitscomboBox.setCurrentIndex(int(val))
                if 'sum' == key:
                    self.uart_sum_comboBox.setCurrentIndex(int(val))
                if'stops' == key:
                    self.stop_cnt_comboBox.setCurrentIndex(int(val))
                if 'rec_timeout' == key:
                    self.spinBox.setValue(int(val))
        except Exception as e:
            msg = printf_except_info(e)
            if self.msg != None:
                self.msg.emit({'cmd':UART_ST_OPEN_ERR,"data":msg})

    def set_open_st(self):
        try:
            if self.open_st == False:
                self.cfg['port'] = self.uart_port_comboBox.currentText()
                self.cfg['bandrate'] = self.band_rate_list[self.uart_bandrate_comboBox.currentIndex()]
                self.cfg['data_bits'] = self.data_bits[self.uart_bitscomboBox.currentIndex()]
                self.cfg['sum'] = self.sum_list[self.uart_sum_comboBox.currentIndex()]
                self.cfg['stops'] = self.stops_list[self.stop_cnt_comboBox.currentIndex()]
                self.cfg['rec_timeout'] = self.spinBox.value()
                if self.msg != None:
                    cfg = self.get_cfg_info()
                    self.msg.emit({'cmd':UART_ST_SAVE_DATA, 'data':cfg})
                if self.cfg['port'] == '刷新':
                    return 
            
                self.uart_hd = serial.Serial(
                port=self.cfg['port'],              # number of device, numbering starts at
                baudrate=self.cfg['bandrate'],          # baud rate
                bytesize=self.cfg['data_bits'],     # number of databits
                parity=self.cfg['sum'],     # enable parity checking
                stopbits=self.cfg['stops'],  # number of stopbits
                timeout=None,           # set a timeout value, None for waiting forever
                xonxoff=0,              # enable software flow control
                rtscts=0,               # enable RTS/CTS flow control
                interCharTimeout=None   # Inter-character timeout, None to disable
                    )
                self.cmd_lock.acquire()
                self.open_st = True
                self.cmd_lock.release()
                self.uart_thread = threading.Thread(None, target=self.uart_rec_task)
                self.uart_thread.start()
                self.pushButton.setText('关闭')
            else:
                self.cmd_lock.acquire()
                self.open_st = False
                self.cmd_lock.release()
                
                
                self.pushButton.setText('打开')
        except Exception as e:
            msg = printf_except_info(e)
            if self.msg != None:
                self.msg.emit({'cmd':UART_ST_OPEN_ERR,"data":msg})

    def slot_uart_com_change(self, name):
        if name == '刷新':
            self.new_cfg()

    def stopx(self):
        if self.uart_hd != None:
            self.open_st = False
            time.sleep(0.3)

    def new_cfg(self):
        port = list(serial.tools.list_ports.comports())
        uart_name = []
        for temp in port:
            uart_name.append(temp.name)
            # print(temp.name,temp.manufacturer)

        if len(uart_name) > 0:
            uart_name.append('刷新')
            self.uart_port_comboBox.clear()
            self.uart_port_comboBox.addItems(uart_name)

    def __init__(self, msg:pyqtSignal, uart_cfg:dict):
        super(uart_cfg_window, self).__init__()
        self.setupUi(self)
        self.retranslateUi(self)
        self.new_cfg()

        self.msg = msg
        self.cfg = uart_cfg

    def repeat_send(self, run, period:int, data:bytearray):
        if run == True and len(data) > 0:
            self.cmd_lock.acquire()
            self.repeat_send_mark = True
            self.repeat_send_data = data
            self.repeat_send_period = period
            self.cmd_lock.release()
        else:
            self.cmd_lock.acquire()
            self.repeat_send_mark = False
            self.cmd_lock.release()
        pass

    def send_data(self, data:bytearray):
        try:
            if self.open_st == False:
                return UART_ST_NOT_INIT
            else:
                self.uart_hd.write(data)
                self.uart_hd.flush()
        except Exception as e:
            msg = printf_except_info(e)
            if self.msg != None:
                self.msg.emit({'cmd':UART_ST_OPEN_ERR,"data":msg})
        pass







